#include <func.h>
#include "head.h"
int recvn(int netFd, void *p, int n){
    int total = 0;
    int ret;
    char *pTmp = (char *)p;
    while(total < n){
        ret = recv(netFd, pTmp + total, n - total, 0);
        ERROR_CHECK(ret, -1, "recv");
        total += ret;
    }
    return 0;
}

int getFileName(char *fileName, const char *curPath){
    int lastSlash = 0;
    for(int i = strlen(curPath) - 1; i != 0; i--){
        if(curPath[i] != '/')
            lastSlash++;
        else
            break;
    }
    strncpy(fileName, curPath + (strlen(curPath) - lastSlash), lastSlash);
    return 0;
}

int recvFile(char *argv, int sockFd){
    //gets /lsx/file
    char buf[1024] = {0};
    recv(sockFd, buf, 1, 0);//接收服务端信号，判断服务器是否存在该文件
    if(strcmp(buf, "0") == 0){
        puts("No such file.");
        return 0;
    }
    //得到文件大小
    int dataLength;
    long fileSize;
    recvn(sockFd, &dataLength, sizeof(int));
    recvn(sockFd, &fileSize, sizeof(fileSize));
    printf("filesize = %lu\n", fileSize);
    char arr[100] = "";
    strcpy(arr, argv);
    char *command = strtok(arr, " ");
    char *curPath = strtok(NULL, " ");
    char fileName[200] = {0};
    getFileName(fileName, curPath);
    printf("%s\n", fileName);
    int fd = open(fileName, O_RDWR|O_CREAT|O_EXCL, 0666);
    off_t downSize = 0;
    off_t lastSize = 0;
    off_t slice = fileSize/1000;
    long notRecvFileSize;
    if(fd == -1){//文件已存在 对文件大小进行判断
        struct stat statbuf;
        fd = open(fileName, O_RDWR, 0666);  //重新获得fd
        fstat(fd, &statbuf);
        if((fileSize - statbuf.st_size) == 0){  //文件已下载（秒传）
            puts("Download finish.");
            send(sockFd, "1", 1, MSG_NOSIGNAL);
            return 0;
        }
        else{
            //文件已存在 但尚未传送完
            lastSize = statbuf.st_size;
            downSize = statbuf.st_size;
            send(sockFd, "0", 1, MSG_NOSIGNAL);
            memcpy(buf, &statbuf.st_size, sizeof(statbuf.st_size));
            send(sockFd, buf, sizeof(statbuf.st_size), MSG_NOSIGNAL); 
            //无论文件是否存在都要发送一个长度给服务端，让其进行ls操作
            //char *p = (char *)mmap(NULL, fileSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
            //recvn(sockFd, p, fileSize - statbuf.st_size);
            lseek(fd, 0, SEEK_END);
            while(fileSize - downSize > sizeof(buf)){
                bzero(buf, sizeof(buf));
                recvn(sockFd, buf, sizeof(buf));
                downSize += sizeof(buf);
                if(downSize - lastSize > slice){
                    printf("%lf%s\r", 100.0*downSize/fileSize, "%");
                    fflush(stdout);
                    lastSize = downSize;
                }
                write(fd, buf, sizeof(buf));
            }
            if(fileSize - downSize > 0){
                recvn(sockFd, buf, fileSize - downSize);
                write(fd, buf, fileSize - downSize);
            }
            printf("100.00000%s\n", "%"); 
        }
    }
    else{//文件未存在
        lastSize = 0;
        downSize = 0;
        send(sockFd, "0", 1, MSG_NOSIGNAL); //文件未存在或文件尚未传送完，服务端收到的信号都为0
        bzero(buf, sizeof(buf));
        send(sockFd, buf, sizeof(fileSize), MSG_NOSIGNAL);
        //ftruncate(fd, fileSize);
        //char *p = (char *)mmap(NULL, fileSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        //recvn(sockFd, p, fileSize);
        while(fileSize - downSize > sizeof(buf)){
            bzero(buf, sizeof(buf));
            recvn(sockFd, buf, sizeof(buf));
            downSize += sizeof(buf);
            if(downSize - lastSize > slice){
                printf("%lf%s\r", 100.0*downSize/fileSize, "%");
                fflush(stdout);
                lastSize = downSize;
            }
            write(fd, buf, sizeof(buf));
        }
        if(fileSize - downSize > 0){
            recvn(sockFd, buf, fileSize - downSize);
            write(fd, buf, fileSize - downSize);
        }
        printf("100.00000%s\n", "%"); 
    }
}//客户端接收来自服务端的文件
